/**
 *  文档用于解决js运算失真问题
 *   运算原则均为输入数字有几位小数结果为几位小数
 *  建议传入String类型
 *  防止数字出现小数位数和预想不同（1.00 为number类型时系统会自动转化为1）
 *  1148692.89*10
 *
 *
 */

/**
 *  加法
 *
 * @param {String} num1
 * @param {String} num2
 * @returns
 */
Math.add = function add(...reset) {
  // 判断是否为数字
  if (reset.length < 2) return '至少输入两位数字'

  let maxLen = 0
  for (const key in reset) {
    if (isNaN(Number(reset[key]))) { return '非数字' }
    maxLen = Math.max(maxLen, judgeLen(reset[key]))
  }
  let result = 0
  reset.forEach(item => {
    result += transferInt(item, maxLen)
  })
  // 格式化结果
  return formatNumToFloat(result / Math.pow(10, maxLen), maxLen)
}
/**
 *  乘法
 *
 * @param {String} num1
 * @param {String} num2
 * @returns
 */
Math.mul = function mul(num1, num2, length) {
  // 判断是否为数字
  if (isNaN(Number(num1)) || isNaN(Number(num2))) { return '非数字' }
  // 判断数字为几位小数
  const len1 = judgeLen(num1)
  const len2 = judgeLen(num2)
  // 判断最大位数
  const maxLen = Math.max(len1, len2)
  num1 = transferInt(num1, maxLen)
  num2 = transferInt(num2, maxLen)
  length !== undefined || (length = maxLen)
  // 格式化结果
  return formatNumToFloat(num1 * num2 / Math.pow(10, maxLen * 2), length)
}

/**
 *  乘法  如果结果小数位数小于传入长度 则取结果小数位数
 *
 * @param {String} num1
 * @param {String} num2
 * @returns
 */
Math.mu = function mu(num1, num2, length) {
  // 判断是否为数字
  if (isNaN(Number(num1)) || isNaN(Number(num2))) { return '非数字' }
  // 判断数字为几位小数
  const len1 = judgeLen(num1)
  const len2 = judgeLen(num2)
  // 判断最大位数
  const maxLen = Math.max(len1, len2)
  num1 = transferInt(num1, maxLen)
  num2 = transferInt(num2, maxLen)
  length !== undefined || (length = maxLen)
  const result = num1 * num2 / Math.pow(10, maxLen * 2)
  const resultLen = new RegExp(/[.]/).test(result) ? result.toString().split('.')[1].length : 0
  if (length > resultLen) {
    length = resultLen
  }
  // 格式化结果
  return formatNumToFloat(result, length)
}

/**
 *  除法
 *
 * @param {String} num1
 * @param {String} num2
 * @param {Number} length   取几位小数
 * @returns
 */
Math.div = function div(num1, num2, length) {
  if (+num2 === 0) {
    return 'NaN'
  }
  // 判断是否为数字
  if (isNaN(Number(num1)) || isNaN(Number(num2))) { return '非数字' }
  // 判断数字为几位小数
  const len1 = judgeLen(num1)
  const len2 = judgeLen(num2)
  // 判断最大位数
  const maxLen = Math.max(len1, len2)
  num1 = transferInt(num1, maxLen)
  num2 = transferInt(num2, maxLen)
  length !== undefined || (length = maxLen)
  return formatNumToFloat(num1 / num2, length)
}

/**
 *  除法  如果结果小数位数小于传入长度 则取结果小数位数
 *
 * @param {String} num1
 * @param {String} num2
 * @param {Number} length   取几位小数
 * @returns
 */
Math.di = function di(num1, num2, length) {
  if (+num2 === 0) {
    return 'NaN'
  }
  // 判断是否为数字
  if (isNaN(Number(num1)) || isNaN(Number(num2))) { return '非数字' }
  // 判断数字为几位小数
  const len1 = judgeLen(num1)
  const len2 = judgeLen(num2)
  // 判断最大位数
  const maxLen = Math.max(len1, len2)
  num1 = transferInt(num1, maxLen)
  num2 = transferInt(num2, maxLen)
  length !== undefined || (length = maxLen)
  const result = num1 / num2
  const resultLen = judgeLen(result)
  if (length > resultLen) {
    length = resultLen
  }
  return formatNumToFloat(result, length)
}

/**
 *  格式化数字小数点位数（需要几位小数则添加或删除几位小数） 四舍五入
 *
 * @param {*} num
 * @param {*} floatLen  小数点位数
 */
function formatNumToFloat(num, floatLen) {
  return Number(num).toFixed(floatLen)
}

/**
 *  判断位数的小数位数
 *
 * @param {*} num
 * return   位数
 */
function judgeLen(num) {
  if (/[.]/.test(num)) {
    let length = String(num).split('.')[1].length
    length = length > 8 ? 8 : length
    return length
  }
  return 0
}
/**
 *  小数转化为整数
 *
 * @param {*} num 小数
 * @param {*} len 乘以的倍数
 * return   返回的整数
 */
function transferInt(num, len) {
  if (Math.abs(num) < 0.000001) return 0
  const supplement = num > 0 ? 0.000001 : -0.000001
  const result = num * Math.pow(10, len) + supplement
  return Number(String(result).split('.')[0])
}
